package saas.baseinfo.service.global;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import saas.baseinfo.service.global.entity.BaseResponseEntity;
import saas.baseinfo.service.global.entity.ErrorCodes;
import saas.baseinfo.service.utils.MessageUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局异常处理类
 */
@ControllerAdvice
@Component
@Slf4j
public class GlobalExceptionHandler {

    private static HttpHeaders headers = new HttpHeaders();

    static {
        headers.set("Access-Control-Allow-Origin", "*");
        headers.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    }

    @Autowired
    private MessageSource messageSource;

    /**
     * 处理其他异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseEntity exceptionHandler(HttpServletRequest req, Exception e) {
        recordErrorLog(req, e);
        headers.set("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers") + ", Content-Type");
        String message = MessageUtils.get("500");
        return new ResponseEntity<>(BaseResponseEntity.error(message), headers, getStatus(req));
    }

    /**
     * 业务异常处理
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public ResponseEntity BusinessExceptionHandler(HttpServletRequest req, BusinessException e) {
        recordErrorLog(req, e);
        String errorCode = ErrorCodes.BUSINESS_EXCEPTION_PREFIX + e.getErrorCode();
        String message = null;
        headers.set("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers") + ", Content-Type");
        try {
            message = MessageUtils.get(errorCode, e.getArgs());
        } catch (NoSuchMessageException ex) {
            return new ResponseEntity<>(BaseResponseEntity.error(errorCode, e.getMessage()), headers, HttpStatus.OK);
        }
        return new ResponseEntity<>(BaseResponseEntity.error(errorCode, message), headers, HttpStatus.OK);
    }

    private void recordErrorLog(HttpServletRequest req, Exception e) {
        log.error("Access URI: {} an error occurred", req.getRequestURI(), e);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        try {
            return HttpStatus.valueOf(statusCode);
        } catch (Exception ex) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }
}
